﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using PocketMahjong.Core;
using System.Windows.Forms;

namespace PocketMahjong
{
	class BoardController
	{
		private BoardView _view;
		private bool _hintMode;
		private Stack<Cell> _undoStack;

		private Board Board
		{
			get { return _view.Board; }
			set { _view.Board = value; }
		}

		public BoardController(BoardView view)
		{
			_view = view;
			_undoStack = new Stack<Cell>();
		}

		internal void ClickTile(Position position)
		{
			if (_hintMode)
			{
				Board.Selection.Clear();
				_hintMode = false;
			}

			if (Board.Selection.Contains(position) || !Board.IsFree(position))
				return;

			if (Board.Selection.Count > 0)
			{
				if (Board[Board.Selection[0]].Match(Board[position]))
					RemovePair(position, Board.Selection[0]);
				else
				{
					Board.Selection.Clear();
					Board.Selection.Add(position);
				}
			}
			else
				Board.Selection.Add(position);
			_view.UpdateView();
			CheckGame();
		}

		private void RemovePair(Position p1, Position p2)
		{
			_undoStack.Push(new Cell(p1, Board[p1]));
			_undoStack.Push(new Cell(p2, Board[p2]));
			Board[p1] = null;
			Board[p2] = null;
			Board.Selection.Clear();
		}

		private void CheckGame()
		{
			if (Board.TilesCount == 0)
				MessageBox.Show("You won!", "Pocket Mahjong");
			else if (Board.PayersCount == 0)
				MessageBox.Show("Game over.", "Pocket Mahjong");
		}

		internal void Undo()
		{
			if (_undoStack.Count > 0)
			{
				Board.Selection.Clear();
				RestoreCell();
				RestoreCell();
				_view.UpdateView();
			}
		}

		private void RestoreCell()
		{
			var c = _undoStack.Pop();
			Board[c.Position] = c.Tile;
		}

		internal void StartNewGame()
		{
			var lay = LayoutProvider.GetLayout(Config.Instance.Layout);
			IArrangeStrategy ar;
			if (Config.Instance.IsRandom)
				ar = new RandomArrange();
			else
				ar = new SolvableArrange();
			Board = new Board(lay, ar);
			_view.UpdateView();
		}

		internal void Restart()
		{
			Board.Restart();
			_view.UpdateView();
		}

		internal void ShowHint()
		{
			_hintMode = true;
			Board.Selection.Clear();
			foreach (var pair in Board.GetPairs())
			{
				Board.Selection.Add(pair.Position1);
				Board.Selection.Add(pair.Position2);
			}
			_view.UpdateView();
		}
	}
}
